package com.dlc.shop.multishop.controller;

import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.dlc.shop.bean.app.dto.MyOrderDto;
import com.dlc.shop.bean.enums.DeliveryType;
import com.dlc.shop.bean.enums.OrderStatus;
import com.dlc.shop.bean.event.OrderChangeAddrEvent;
import com.dlc.shop.bean.model.Order;
import com.dlc.shop.bean.model.OrderItem;
import com.dlc.shop.bean.model.OrderVirtualInfo;
import com.dlc.shop.bean.model.UserAddrOrder;
import com.dlc.shop.bean.param.OrderChangeAddrParam;
import com.dlc.shop.bean.param.OrderParam;
import com.dlc.shop.bean.vo.UnDeliveryOrderExcelVO;
import com.dlc.shop.common.annotation.SysLog;
import com.dlc.shop.common.exception.YamiShopBindException;
import com.dlc.shop.common.i18n.I18nMessage;
import com.dlc.shop.common.response.ResponseEnum;
import com.dlc.shop.common.response.ServerResponseEntity;
import com.dlc.shop.common.util.PageParam;
import com.dlc.shop.delivery.common.param.DeliveryOrderItemParam;
import com.dlc.shop.delivery.common.service.DeliveryOrderService;
import com.dlc.shop.delivery.common.service.OrderSelfStationService;
import com.dlc.shop.security.multishop.util.SecurityUtils;
import com.dlc.shop.service.*;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.Valid;
import lombok.AllArgsConstructor;
import org.springframework.context.ApplicationContext;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @author lgh on 2018/09/15.
 */
@RestController
@RequestMapping("/order/order")
@Tag(name = "订单接口")
@AllArgsConstructor
public class OrderController {

    private final OrderService orderService;

    private final OrderItemService orderItemService;
    private final OrderVirtualInfoService orderVirtualInfoService;

    private final UserAddrOrderService userAddrOrderService;

    private final OrderExcelService orderExcelService;

    private final DeliveryOrderService deliveryOrderService;

    private final ApplicationContext applicationContext;

    private final OrderSelfStationService orderSelfStationService;

    @GetMapping("/page")
    @Operation(summary = "分页获取订单列表" , description = "分页获取订单列表")
    @PreAuthorize("@pms.hasPermission('order:order:page')")
    public ServerResponseEntity<IPage<Order>> page(OrderParam orderParam, PageParam<Order> page) {
        Long shopId = SecurityUtils.getShopUser().getShopId();
        orderParam.setShopId(shopId);
        IPage<Order> orderPage = orderService.pageOrdersDetailByOrderParam(page, orderParam);
        return ServerResponseEntity.success(orderPage);
    }

    @GetMapping("/orderInfo/{orderNumber}")
    @Operation(summary = "根据订单号获取订单信息" , description = "根据订单号获取订单信息")
    @PreAuthorize("@pms.hasPermission('order:order:info')")
    public ServerResponseEntity<Order> info(@PathVariable("orderNumber") String orderNumber) {
        Long shopId = SecurityUtils.getShopUser().getShopId();
        Order order = orderService.getOrderByOrderNumberAndShopId(orderNumber, shopId, true);
        List<OrderItem> orderItems = orderItemService.getOrderItemsByOrderNumber(orderNumber,true);
        order.setOrderItems(orderItems);
        UserAddrOrder userAddrOrder = userAddrOrderService.getById(order.getAddrOrderId());
        order.setUserAddrOrder(userAddrOrder);
        if(Objects.equals(order.getOrderMold(),1)){
            List<OrderVirtualInfo> orderVirtualInfos = orderVirtualInfoService.list(new LambdaQueryWrapper<OrderVirtualInfo>().eq(OrderVirtualInfo::getOrderNumber, orderNumber).eq(OrderVirtualInfo::getIsWriteOff, 0));
            List<String> codes = new ArrayList<>();
            if(CollectionUtil.isNotEmpty(orderVirtualInfos)){
                codes = orderVirtualInfos.stream().map(OrderVirtualInfo::getWriteOffCode).collect(Collectors.toList());
            }
            order.setWriteOffCodes(codes);
        }
        return ServerResponseEntity.success(order);
    }

    /**
     * 本方法为国内商家查询国际订单所用接口，应该在国外站部署，国内商家调用获取国外订单列表
     *
     * @param orderParam 订单查询参数对象
     * @param page 分页参数对象，用于指定分页信息
     */
    @GetMapping("/multishopFromChina/page")
    @Operation(summary = "分页获取订单列表" , description = "分页获取订单列表")
    // @PreAuthorize("@pms.hasPermission('order:order:page')")
    public ServerResponseEntity<IPage<Order>> pageMultishopFromChina(OrderParam orderParam, PageParam<Order> page) {
        Long shopId = SecurityUtils.getShopUser().getShopId();
        orderParam.setShopId(shopId);
        // 调用订单服务的方法，根据订单查询参数和分页参数获取订单的分页详细信息
        IPage<Order> orderPage = orderService.pageOrdersDetailByOrderParam(page, orderParam);
        return ServerResponseEntity.success(orderPage);
    }

    @GetMapping("/multishopFromChina/orderInfo/{orderNumber}")
    @Operation(summary = "根据订单号获取订单信息" , description = "根据订单号获取订单信息")
    //@PreAuthorize("@pms.hasPermission('order:order:info')")
    public ServerResponseEntity<Order> multishopFromChinaOrderInfo(@PathVariable("orderNumber") String orderNumber) {
        Long shopId = SecurityUtils.getShopUser().getShopId();
        Order order = orderService.getOrderByOrderNumberAndShopId(orderNumber, shopId, true);
        List<OrderItem> orderItems = orderItemService.getOrderItemsByOrderNumber(orderNumber,true);
        order.setOrderItems(orderItems);
        UserAddrOrder userAddrOrder = userAddrOrderService.getById(order.getAddrOrderId());
        order.setUserAddrOrder(userAddrOrder);
        if(Objects.equals(order.getOrderMold(),1)){
            List<OrderVirtualInfo> orderVirtualInfos = orderVirtualInfoService.list(new LambdaQueryWrapper<OrderVirtualInfo>().eq(OrderVirtualInfo::getOrderNumber, orderNumber).eq(OrderVirtualInfo::getIsWriteOff, 0));
            List<String> codes = new ArrayList<>();
            if(CollectionUtil.isNotEmpty(orderVirtualInfos)){
                codes = orderVirtualInfos.stream().map(OrderVirtualInfo::getWriteOffCode).collect(Collectors.toList());
            }
            order.setWriteOffCodes(codes);
        }
        return ServerResponseEntity.success(order);
    }

    @GetMapping("/getOrderByCode")
    @Operation(summary = "通过提货码获取自提订单" , description = "商家扫码获取自提订单")
    @Parameter(name = "code", description = "提货码" , required = true)
    public ServerResponseEntity<Order> getStationOrderByCode(@RequestParam(value = "code") String code) {
        Long shopId = SecurityUtils.getShopUser().getShopId();
        MyOrderDto myOrderDto = orderSelfStationService.getOrderByStationCode(null, shopId, code);
        Order order = orderService.getOrderByOrderNumberAndShopId(myOrderDto.getOrderNumber(), shopId, true);
        List<OrderItem> orderItems = orderItemService.getOrderItemsByOrderNumber(myOrderDto.getOrderNumber(),true);
        order.setOrderItems(orderItems);
        UserAddrOrder userAddrOrder = userAddrOrderService.getById(order.getAddrOrderId());
        order.setUserAddrOrder(userAddrOrder);
        if(Objects.equals(order.getOrderMold(),1)){
            List<OrderVirtualInfo> orderVirtualInfos = orderVirtualInfoService.list(new LambdaQueryWrapper<OrderVirtualInfo>().eq(OrderVirtualInfo::getOrderNumber, myOrderDto.getOrderNumber()).eq(OrderVirtualInfo::getIsWriteOff, 0));
            List<String> codes = new ArrayList<>();
            if(CollectionUtil.isNotEmpty(orderVirtualInfos)){
                codes = orderVirtualInfos.stream().map(OrderVirtualInfo::getWriteOffCode).collect(Collectors.toList());
            }
            order.setWriteOffCodes(codes);
        }
        return ServerResponseEntity.success(order);
    }

    @PutMapping("/changeAmount")
    @Operation(summary = "修改订单金额" , description = "修改订单金额")
    @PreAuthorize("@pms.hasPermission('order:order:update')")
    public ServerResponseEntity<Void> changeAmount(@RequestBody Order order) {
        if (order.getFreightAmount() < 0) {
            // 运费不能小于零
            throw new YamiShopBindException("yami.product.dvy.fee");
        }
        if (Objects.isNull(order.getFreightAmount())) {
            order.setFreightAmount(0.00);
        }
        orderService.changeAmount(order);
        return ServerResponseEntity.success();
    }

    @GetMapping("/getChangeAmount")
    @Operation(summary = "查询修改订单地址后的运费")
    @PreAuthorize("@pms.hasPermission('order:order:update')")
    public ServerResponseEntity<Double> getChangeAmount(OrderChangeAddrParam order) {
        double changeAmount = 0.0;
        OrderChangeAddrEvent orderChangeAddrEvent = new OrderChangeAddrEvent(order, changeAmount);
        applicationContext.publishEvent(orderChangeAddrEvent);
        return ServerResponseEntity.success(orderChangeAddrEvent.getChangeAmount());
    }

    @PutMapping("/changeUserAddr")
    @Operation(summary = "修改用户订单地址" , description = "修改用户订单地址")
    @PreAuthorize("@pms.hasPermission('order:order:update')")
    public ServerResponseEntity<String> changeUserAddr(@RequestBody @Valid Order order) {
        Order orderDb = orderService.getOne(new LambdaQueryWrapper<Order>()
                .eq(Order::getOrderId, order.getOrderId())
                .eq(Order::getOrderNumber, order.getOrderNumber())
        );
        if (orderDb.getStatus() <= OrderStatus.PADYED.value() || Objects.equals(orderDb.getStatus(), OrderStatus.WAIT_GROUP.value())) {
            UserAddrOrder userAddrOrder = order.getUserAddrOrder();
            userAddrOrderService.updateAddrInfoById(userAddrOrder, orderDb);
        } else {
            // 订单状态异常，无法更改订单地址
            throw new YamiShopBindException("yami.order.status.error");
        }
        // 修改成功
        return ServerResponseEntity.success(ResponseEnum.OK.value(), I18nMessage.getMessage("yami.activity.update.success"));
    }

    @SysLog("修改订单备注")
    @PutMapping("/changeOrderRamark")
    @Operation(summary = "修改订单备注" , description = "修改订单备注")
    @PreAuthorize("@pms.hasPermission('order:order:update')")
    public ServerResponseEntity<String> changeOrderRamark(@RequestBody @Valid Order order) {
        Order orderDb = orderService.getOne(new LambdaQueryWrapper<Order>()
                .eq(Order::getOrderId, order.getOrderId())
                .eq(Order::getOrderNumber, order.getOrderNumber())
        );
        orderDb.setShopRemarks(order.getShopRemarks());
        orderService.updateById(orderDb);
        // 修改成功
        return ServerResponseEntity.success(ResponseEnum.SHOW_SUCCESS.value(), I18nMessage.getMessage("yami.activity.update.success"));
    }

    @GetMapping("/soldExcel")
    @Operation(summary = "导出excel" , description = "导出订单excel")
    @PreAuthorize("@pms.hasPermission('order:order:export')")
    public void soldExcel(OrderParam orderParam, HttpServletResponse response) {
        Long shopId = SecurityUtils.getShopUser().getShopId();
        orderParam.setShopId(shopId);
        orderExcelService.soldExcel(orderParam, response);
    }

    @GetMapping("/unDeliveryOrderExcel")
    @Operation(summary = "导出待发货订单" , description = "导出待发货订单")
    @PreAuthorize("@pms.hasPermission('order:order:exportunorder')")
    public void unDeliveryOrderExcel(OrderParam orderParam, HttpServletResponse response) {
        Long shopId = SecurityUtils.getShopUser().getShopId();
        orderParam.setShopId(shopId);
        orderExcelService.unDeliveryOrderExcel(orderParam, response);
    }

    @Operation(summary = "导入待发货文件" , description = "导入待发货文件")
    @PostMapping("/exportOrderExcel")
    @ResponseBody
    @PreAuthorize("@pms.hasPermission('order:order:exportunorder')")
    public ServerResponseEntity<String> exportOrderExcel(@RequestParam("orderExcelFile") MultipartFile orderExcelFile) throws Exception {
        if (Objects.isNull(orderExcelFile)) {
            throw new YamiShopBindException("yami.network.busy");
        }
        Long shopId = SecurityUtils.getShopUser().getShopId();
        List<UnDeliveryOrderExcelVO> orderList = new ArrayList<>();
        String errorMsg = orderExcelService.exportOrderExcel(orderExcelFile, shopId, orderList);
        if (Objects.nonNull(errorMsg)) {
            return ServerResponseEntity.success(errorMsg);
        }
        //无错误再发货
        for (UnDeliveryOrderExcelVO orderExcelVO : orderList) {
            DeliveryOrderItemParam deliveryOrderParam = new DeliveryOrderItemParam();
            deliveryOrderParam.setOrderNumber(orderExcelVO.getOrderNumber());
            deliveryOrderParam.setDeliveryType(orderExcelVO.getDvyType());
            if (Objects.equals(orderExcelVO.getDvyType(), DeliveryType.EXPRESS.getValue())) {
                deliveryOrderParam.setDvyFlowId(orderExcelVO.getDvyFlowId());
                deliveryOrderParam.setDvyId(orderExcelVO.getDvyId());
            }
            List<OrderItem> selectOrderItems = new ArrayList<>();
            for (OrderItem orderItem : orderExcelVO.getOrderItemList()) {
                OrderItem deliveryItem = new OrderItem();
                deliveryItem.setOrderItemId(orderItem.getOrderItemId());
                deliveryItem.setChangeNum(orderItem.getStatus() == -1 ? orderItem.getChangeNum() : orderItem.getStatus());
                deliveryItem.setStatus(orderItem.getStatus());
                deliveryItem.setProdCount(orderItem.getChangeNum());
                selectOrderItems.add(deliveryItem);
            }
            deliveryOrderParam.setSelectOrderItems(selectOrderItems);
            deliveryOrderService.saveDeliveriesInfo(deliveryOrderParam, shopId);
        }
        return ServerResponseEntity.success("导入成功！");
    }
    @GetMapping("/getOrderByUserId")
    @Operation(summary = "分页获取用户订单列表" , description = "分页获取用户订单列表")
    @Parameter(name = "userId", description = "用户id" )
    @PreAuthorize("@pms.hasPermission('order:order:pageByUserId')")
    public ServerResponseEntity<IPage<Order>> getOrderByUserId(PageParam<Order> page, String userId){
        Long shopId = SecurityUtils.getShopUser().getShopId();
        IPage<Order> pages = orderService.pageByUserIdAndShopId(page,userId,shopId);
        return ServerResponseEntity.success(pages);
    }

    @PostMapping("/orderCommissionSettlement")
    @Operation(summary = "测试用例方法调用订单结算接口" , description = "分页获取用户订单列表")
    public ServerResponseEntity<Void> orderCommissionSettlement(@RequestBody Order order){
        orderService.orderCommissionSettlement(Arrays.asList(order));
        return ServerResponseEntity.success();
    }


}
